package com.hpq.user.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.hpq.common.constant.RedisConstant;
import com.hpq.common.utils.RedisUtils;
import com.hpq.user.dao.UserDAO;
import com.hpq.user.domain.model.User;
import com.hpq.user.service.UserService;
import com.hpq.user.service.WxMsgService;
import com.hpq.user.service.adapter.TextBuilder;
import com.hpq.user.service.adapter.UserAdapter;
import com.hpq.websocket.domain.dto.LoginMessageDTO;
import com.hpq.websocket.service.WebSocketService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.util.Objects;

@Slf4j
@Service
public class WxMsgServiceImpl implements WxMsgService {
    @Autowired
    private UserDAO userDao;
    @Autowired
    private UserService userService;
    @Autowired
    @Lazy
    private WxMpService wxMpService;
    @Autowired
    @Lazy
    private WebSocketService webSocketService;
    @Value("${coffeechat.wx.callback}")
    private String callback;
    private static final String URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
    /**
     * 扫码事件
     * @param wxMpXmlMessage
     * @return
     */
    @Override
    public WxMpXmlOutMessage scan(WxMpXmlMessage wxMpXmlMessage) {
        String openId = wxMpXmlMessage.getFromUser();
        Integer code = getEventKey(wxMpXmlMessage);
        if(Objects.isNull(code)){
            return null;
        }
        User user = userDao.getByOpenId(openId);

        boolean registered = Objects.nonNull(user);
        boolean authorized = false;
        if(registered){
            authorized = StrUtil.isNotBlank(user.getAvatar());
        }

        // 用户已经注册并授权
        if(registered && authorized ){
            //登陆成功逻辑 ，通过code找到channel向前端推送消息
//        //扫描登录成功
            webSocketService.scanLoginSuccess(code,user.getId());
            return null;
        }
        // 用户未注册
        if(!registered){
            log.info("用户未注册，开始注册用户：openId:{}", openId);
            User userSave = UserAdapter.buildUserSave(openId);
            userService.register(userSave);
        }
        // 扫码事件处理，推送链接让用户授权
        log.info("扫码事件处理，openId:{},code:{}", code, openId);
        //todo 扫码
        String authorizeUrl = String.format(URL, wxMpService.getWxMpConfigStorage().getAppId(), URLEncoder.encode(callback+"/wx/portal/public/callBack"));
        return TextBuilder.build(wxMpXmlMessage, "请点击链接授权：<a href=\"" + authorizeUrl + "\">登录</a>");
    }

    /**
     *  用户授权
     * @param userInfo
     */
    @Override
    public void saveAuthorize(WxOAuth2UserInfo userInfo) {
        User user = userDao.getByOpenId(userInfo.getOpenid());
        if(StringUtils.isEmpty(user.getName())){
            filledUsername(user.getId(),userInfo);
        }
        Integer code = RedisUtils.get(RedisConstant.getKey(RedisConstant.USER_TOKEN_KEY, user.getId()),Integer.class);
        LoginMessageDTO messageDTO = new LoginMessageDTO(user.getId(), code);
    }

    private void filledUsername(Long uid, WxOAuth2UserInfo userInfo) {
        User update = UserAdapter.buildAuthorizeUser(uid, userInfo);
        for (int i = 0; i < 5; i++) {
            try {
                userDao.updateById(update);
                return;
            } catch (DuplicateKeyException e) {
                log.info("fill userInfo duplicate uid:{},info:{}", uid, userInfo);
            } catch (Exception e) {
                log.error("fill userInfo fail uid:{},info:{}", uid, userInfo);
            }
            update.setName("名字重置" + RandomUtil.randomInt(100000));
        }


    }

    /**
     * 处理登录码逻辑
     * @param wxMpXmlMessage
     * @return
     */
    private Integer getEventKey(WxMpXmlMessage wxMpXmlMessage) {
        try {
            String eventKey = wxMpXmlMessage.getEventKey();
            //去掉前缀
            String code = eventKey.replace("qrscene_","");
            return Integer.parseInt(code);
        } catch (NumberFormatException e) {
            log.error("getEventKey error: {}",wxMpXmlMessage.getEventKey(), e);
            return null;
        }
    }
}
